package com.xuecheng.teaching.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.teaching.model.dto.CompanyDTO;
import com.xuecheng.api.teaching.model.dto.TeachplanWorkDTO;
import com.xuecheng.api.teaching.model.dto.WorkDTO;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.domain.uaa.LoginUser;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.teaching.agent.CommentApiAgent;
import com.xuecheng.teaching.agent.CourseBaseApiAgent;
import com.xuecheng.teaching.common.constant.TeachingErrorCode;
import com.xuecheng.teaching.common.util.UAASecurityUtil;
import com.xuecheng.teaching.convert.WorkConvert;
import com.xuecheng.teaching.entity.Work;
import com.xuecheng.teaching.entity.WorkRecord;
import com.xuecheng.teaching.mapper.WorkMapper;
import com.xuecheng.teaching.service.WorkRecordService;
import com.xuecheng.teaching.service.WorkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 作业 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class WorkServiceImpl extends ServiceImpl<WorkMapper, Work> implements WorkService {

    @Autowired
    private CourseBaseApiAgent workApiAgent;

    @Autowired
    private WorkRecordService workRecordService;



    /*
     *新增或修改作业
     * 1.判断关键数据
     *    1.1作业信息和公司id（待定：或者运营平台标示）
     *              		不存在：抛出异常
     * 2.核实关键信息
     *      2.1判断作业内容，课程标题是否存在
     *          不存在则抛出异常
     *      2.2判断作业id是否存在
     *              存在：
     *                  根据作业id和状态获取作业信息，如果不空则修改，否则添加
     *              不存在添加作业
     */

    @Transactional  //开启事务
    public WorkDTO createOrModifyWork(WorkDTO workDTO, Long companyId) {
        //1.判断关键数据: 作业信息(作业内容，课程标题)和公司id 是否存在
        if (StringUtil.isBlank(workDTO.getTitle()) ||
                StringUtil.isBlank(workDTO.getQuestion()) ||
                ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(TeachingErrorCode.E_130601);
        }

        WorkDTO resultDTO = null;
        //2. 判断作业id是否存在

        if (ObjectUtils.isEmpty(workDTO.getWorkId())) {
            //执行创建操作
            resultDTO = this.createWork(workDTO, companyId);

        } else {
            //执行修改操作
            resultDTO = this.modifyWork(workDTO, companyId);

        }

        //返回dto数据
        return resultDTO;
    }
    /*
     *  修改作业
     *          1. 判断业务数据
     *                  是否存在
     *                  是否是同一家机构
     *                  是否删除
     *          2. 修改作业信息数据
     *                设置课程内容(question)
     *                设置课程标题(title)
     *                设置修改时间（changeDate）
     *          3. 判断修改的作业是否成功
     *          4. 查询最新数据库作业信息
     *          5. 将po转换为dto
     *          6. 返回数据
     */

    private WorkDTO modifyWork(WorkDTO workDTO, Long companyId) {
        //  1. 判断业务数据:是否存在, 是否是同一家机构,是否删除\
        //     构建LambdaQueryWrapper条件查询对象
        LambdaQueryWrapper<Work> queryWrapper = new LambdaQueryWrapper<>();
        //     添加查询条件
        queryWrapper.eq(Work::getId, workDTO.getWorkId())
                .eq(Work::getCompanyId, companyId)
                .eq(Work::getStatus, CommonEnum.USING_FLAG.getCodeInt());
        //      调用查询数量方法
        int count = this.count(queryWrapper);
        //判断作业数量
        if (count < 1) {
            ExceptionCast.cast(TeachingErrorCode.E_130603);
        }

        //2. 修改作业信息数据
        //   构建LambdaUpdateWrapper条件修改对象
        LambdaUpdateWrapper<Work> updateWrapper = new LambdaUpdateWrapper<>();
        //    添加修改条件
        updateWrapper.eq(Work::getId, workDTO.getWorkId())
                .eq(Work::getStatus, CommonEnum.USING_FLAG.getCodeInt())
                .set(Work::getTitle, workDTO.getTitle())
                .set(Work::getQuestion, workDTO.getQuestion())
                .set(Work::getChangeDate, LocalDateTime.now());
        //      调用修改方法
        boolean update = this.update(updateWrapper);

        // 3.判断修改后的结果
        if (!update) {
            ExceptionCast.cast(TeachingErrorCode.E_130604);
        }

        //4. 查询最新数据库作业信息
        Work po = this.getById(workDTO.getWorkId());

        //5. 将po转换为dto
        WorkDTO dto = WorkConvert.INSTANCE.entity2dto(po);

        // 6. 返回数据
        return dto;


    }

    /*
     *新增作业封装方法
     *      1. 判断业务数据（增加没有业务数据）
     *      2. 判断数据是否要被赋值（默认值）
     *          作业状态赋值（数据库默认赋值 使用态 1）
     *      3.  创建保存作业实体类
     *               设置作业信息
     *               设置课程内容(question)
     *               设置课程标题(title)
     *               设置创建时间(createDate)
     *      4 .判断保存的作业是否成功
     *      5. 查询最新数据库作业信息
     *      6. 将po转换为dto
     *      7. 返回数据
     *
     */
    private WorkDTO createWork(WorkDTO workDTO, Long companyId) {
        //1 创建作业实体类
        Work work = new Work();
        //2.添加数据：机构id，标题，内容，创建人
        work.setCompanyId(companyId);
        work.setTitle(workDTO.getTitle());
        work.setQuestion(workDTO.getQuestion());

        //获取用户数据
        LoginUser user = UAASecurityUtil.getUser();
        //获取用户名
        String userName = user.getUsername();
        //获取公司数据
        CompanyDTO company = UAASecurityUtil.getCompany();
        //获取公司名字
        String companyName = company.getName();
        //添加创建人
        work.setUsername(userName);
        //添加公司名字
        work.setCompanyName(companyName);
        //设置修改时间
        work.setChangeDate(LocalDateTime.now());

        //3.保存数据
        boolean save = this.save(work);
        //4 .判断保存的作业是否成功
        if (!save) {
            ExceptionCast.cast(TeachingErrorCode.E_130601);
        }

        //5. 查询最新数据库作业信息
        Work po = this.getById(work.getId());

        //6. 将po转换为dto
        WorkDTO dto = WorkConvert.INSTANCE.entity2dto(po);

        //7. 返回数据
        return dto;
    }

    @Transactional
    public void removeWork(Long workId, Long companyId) {
        //判断关键数据
        if (ObjectUtils.isEmpty(workId) ||
                ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        // 2.判断业务数据
        // 作业信息是否存在
        LambdaQueryWrapper<Work> workWrapper = new LambdaQueryWrapper<>();
        workWrapper.eq(Work::getId, workId);
        workWrapper.eq(Work::getCompanyId, companyId);
        Work work = this.getOne(workWrapper);
        if (ObjectUtils.isEmpty(work)) {
            ExceptionCast.cast(TeachingErrorCode.E_130407);
        }


        //远程调用查询是否绑定课程计划
        RestResponse<List<TeachplanWorkDTO>> byWorkId4s = workApiAgent.getByWorkId4s(workId);
        if (!(byWorkId4s.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(byWorkId4s.getCode(), byWorkId4s.getMsg());
        }
        List<TeachplanWorkDTO> result = byWorkId4s.getResult();
        if (!(CollectionUtils.isEmpty(result))) {
            ExceptionCast.cast(TeachingErrorCode.E_130411);
        }

        // 4.将本地work信息删除
        LambdaUpdateWrapper<Work> workUpdateWrapper = new LambdaUpdateWrapper<>();
        workUpdateWrapper.eq(Work::getId, workId);
        workUpdateWrapper.set(Work::getStatus, CommonEnum.DELETE_FLAG.getCodeInt());
        boolean update = this.update(workUpdateWrapper);
        if (!update) {
            ExceptionCast.cast(TeachingErrorCode.E_130410);
        }

    }

    /**
     * 分页条件查询课程计划作业列表
     *
     * @param params
     * @param companyId
     * @return
     */
    public PageVO<WorkDTO> queryWorkList(PageRequestParams params, String title, Long companyId) {
        //1.判断关键数据
        //判断分页数据
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }
        //判断公司id
        if (ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //2.构建分页对象
        Page<Work> page = new Page<>(params.getPageNo(), params.getPageSize());
        //3.构建查询条件对象
        LambdaQueryWrapper<Work> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Work::getStatus, CommonEnum.USING_FLAG.getCodeInt());
        //作业模糊查询条件
        if (StringUtil.isNotBlank(title)) {
            queryWrapper.like(Work::getTitle, title);
        }
        //公司id
        queryWrapper.eq(Work::getCompanyId, companyId);
        //4.查询作业信息
        Page<Work> workPage = this.page(page, queryWrapper);
        //作业信息
        List<Work> works = workPage.getRecords();
        //作业数量
        long total = workPage.getTotal();
        //5.po转dto
        List<WorkDTO> dtos = Collections.emptyList();
        if (!(CollectionUtils.isEmpty(works))) {
            dtos = WorkConvert.INSTANCE.entitys2dtos(works);

            for (WorkDTO dto : dtos) {
                RestResponse<List<String>> response = workApiAgent.getCoursePubByWorkId4s(dto.getWorkId());
                dto.setBindCourses(response.getResult());
                LambdaQueryWrapper<WorkRecord> workRecordQuery = Wrappers.lambdaQuery(WorkRecord.class);
                workRecordQuery.eq(WorkRecord::getWorkId, dto.getWorkId());
                int count = workRecordService.count(workRecordQuery);
                dto.setUserNum(count);
            }
        }


        //6.返回数据
        PageVO pageVO = new PageVO(dtos, total, params.getPageNo(), params.getPageSize());
        return pageVO;
    }

    /**
     * 根据Id查询作业信息-远程调用
     *
     * @param workId
     * @return
     */
    @Override
    public RestResponse<WorkDTO> getWorkById4c(Long workId) {
        // 1.判断关键数据
        if (ObjectUtils.isEmpty(workId)) {
            return RestResponse.validfail(CommonErrorCode.E_100101);
        }
        // 2.判断业务数据
        Work work = this.getById(workId);
        if (ObjectUtils.isEmpty(work)) {
            return RestResponse.validfail(TeachingErrorCode.E_130407);
        } else {
            WorkDTO workDTO = WorkConvert.INSTANCE.entity2dto(work);
            return RestResponse.success(workDTO);
        }
    }
}
